/* 文件读取加载部分 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <string.h>
#include "comm.h"

/* map file, get size and memory pos */
void* open_file(char *filename, size_t *pFSize){
	int fd;
	void *start;
	struct stat sb;

	fd = open(filename, O_RDWR); 
	if (0 == fd){
		/* open file fail */
		PRINTF("open file failed\n");
		return NULL;
	}
	
	fstat(fd, &sb); /* read file size */
	start = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if(start == MAP_FAILED) /* if map failed */{
		PRINTF("map failed!\n");
		return NULL;
	}
	
	PRINTF("mem pos:%p\t len:%ld\n", start, sb.st_size); 
	close(fd);

	*pFSize = sb.st_size;

	return start;
}


/* binary search */
void *split_search(BYTE *start, size_t fsize, BYTE *key){
	int i = 0;
	BYTE *end = start + fsize;
	BYTE *key_end;
	BYTE *cursor; 
	int cmp_result;
	BYTE *pre_cursor;
	
	while(1){
		/* find middle pos */
		cursor= start + (end - start)/2; 
		PRINTF("start = %p, end = %p, size=%ld, middle=%p\n", start, end, end-start, cursor);
		// PRINT_LINE(start);
		/* move to \n  then end */
		while (*cursor != '\n' && cursor < end){
			PRINTF("cursor = %p, start = %p, end = %p\n", cursor, start, end);
			cursor ++;
		}
		PRINTF("move finish cursor = %p, start = %p, end = %p\n", cursor, start, end);
		// PRINTF("cursor = %p, end = %p\n", cursor, end);
		if (cursor == end || cursor+1 == end){ 
			/* if cursor is end, find the previous line start */
			PRINTF("cursor == end:\n");
			cursor--;
			while (*cursor != '\n' && cursor > start){
				cursor --;
			}
			cursor++;
			PRINTF("moved to pre line! cursor = %p, start = %p, end = %p\n", cursor, start, end);
			if (cursor < start) cursor = start;
			PRINTF("cursor = %p, start = %p\n", cursor, start);
			PRINT_KEY(cursor);
		}else{
			cursor++; // skip the \r\n
		}
		/* find key string */
		key_end = cursor;
		while (*key_end != ','){
			// PRINTF("key_end++, %p, %p\n", key_end, cursor);
			key_end++;
		}
		//
		// PRINTF("memcmp ");
		// PRINTF(key);PRINTF(",");
		// PRINT_KEY(cursor);
		// PRINTF("%p, %p, %d\n", key_end, cursor, key_end-cursor);
		cmp_result = memcmp(key, cursor, key_end-cursor);
		if (cmp_result == 0){
			/* same! hit! */
			return cursor;
		}else if (cmp_result > 0){
			/* search larger part */
			start = cursor;
		}else {
			/* search less part */
			end = cursor-1;
		}
		if (pre_cursor == cursor){
			return NULL;
		}else{
			pre_cursor = cursor;
		}
	}
	return NULL;
}


